package com.fly.procode.ui;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

import com.fly.procode.core.DateUtil;
import com.fly.procode.core.Service;
import com.fly.procode.process.RunProgress;

/**
 * 
 * swt jface版本
 * 
 * @author 00fly
 * @version [版本号, 2020年4月24日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ProCodeToolSJ
{
    Display display;
    
    Shell shell;
    
    org.eclipse.swt.widgets.List listJava;
    
    org.eclipse.swt.widgets.List listPage;
    
    public ProCodeToolSJ()
    {
        super();
        display = new Display();
        shell = new Shell(display, SWT.MIN | SWT.CLOSE | SWT.ON_TOP);
        InputStream is = this.getClass().getResourceAsStream("/image/icon.gif");
        if (is != null)
        {
            shell.setImage(new Image(display, is));
        }
        shell.setText("代码备份恢复工具 V1.1.0");
        shell.setSize(540, 383);
        Rectangle screeRec = display.getBounds();
        Rectangle shellRec = shell.getBounds();
        if (shellRec.height > screeRec.height)
        {
            shellRec.height = screeRec.height;
        }
        if (shellRec.width > screeRec.width)
        {
            shellRec.width = screeRec.width;
        }
        shell.setLocation((screeRec.width - shellRec.width) / 2, (screeRec.height - shellRec.height) / 2);
        addMenu();
        setContent();
        shell.open();
        while (!shell.isDisposed())
        {
            if (!display.readAndDispatch())
            {
                display.sleep();
            }
        }
        display.dispose();
    }
    
    // main
    public static void main(String[] args)
    {
        new ProCodeToolSJ();
    }
    
    // Menu set
    private void addMenu()
    {
        Menu m = new Menu(shell, SWT.BAR);
        // create a file menu and add an exit item
        MenuItem file = new MenuItem(m, SWT.CASCADE);
        file.setText("文件(&F)");
        file.setAccelerator(SWT.CTRL + 'F');
        Menu filemenu = new Menu(shell, SWT.DROP_DOWN);
        file.setMenu(filemenu);
        MenuItem openMenuItem = new MenuItem(filemenu, SWT.CASCADE);
        openMenuItem.setText("最近备份(&O)");
        openMenuItem.setAccelerator(SWT.CTRL + 'O');
        Menu submenu = new Menu(shell, SWT.DROP_DOWN);
        openMenuItem.setMenu(submenu);
        MenuItem childItem = new MenuItem(submenu, SWT.PUSH);
        childItem.setText("Child");
        MenuItem saveMenuItem = new MenuItem(filemenu, SWT.CASCADE);
        saveMenuItem.setText("最近恢复(&S)");
        saveMenuItem.setAccelerator(SWT.CTRL + 'S');
        Menu submenu2 = new Menu(shell, SWT.DROP_DOWN);
        saveMenuItem.setMenu(submenu2);
        MenuItem childItem2 = new MenuItem(submenu2, SWT.PUSH);
        childItem2.setText("Child2");
        new MenuItem(filemenu, SWT.SEPARATOR);
        MenuItem exitMenuItem = new MenuItem(filemenu, SWT.PUSH);
        exitMenuItem.setText("退出(&X)");
        exitMenuItem.setAccelerator(SWT.CTRL + 'X');
        exitMenuItem.addSelectionListener(new SelectionAdapter()
        {
            @Override
            public void widgetSelected(SelectionEvent e)
            {
                System.exit(0);
            }
        });
        // create a Help menu and add an about item
        MenuItem help = new MenuItem(m, SWT.CASCADE);
        help.setText("帮助(&H)");
        help.setAccelerator(SWT.CTRL + 'H');
        Menu helpmenu = new Menu(shell, SWT.DROP_DOWN);
        help.setMenu(helpmenu);
        MenuItem useMenuItem = new MenuItem(helpmenu, SWT.PUSH);
        useMenuItem.setText("使用指南(&U)");
        new MenuItem(helpmenu, SWT.SEPARATOR);
        MenuItem aboutMenuItem = new MenuItem(helpmenu, SWT.PUSH);
        aboutMenuItem.setText("关于工具(&A)");
        useMenuItem.addSelectionListener(new SelectionAdapter()
        {
            @Override
            public void widgetSelected(SelectionEvent event)
            {
                MessageDialog.openInformation(shell,
                    "使用指南",
                    "请按以下顺序操作：" + "\n 文件备份" + "\n 1. 选择项目源文件的目录。" + "\n 2. 选择需要备份的文件类型。" + "\n 3. 选择备份文件输出目录。" + "\n 4. 导出文件。" + "\n " + "\n 文件恢复 " + "\n 1. 到备份目录下选择备份文件。" + "\n 2. 选择备份文件的恢复目录。" + "\n 3. 恢复文件");
            }
        });
        aboutMenuItem.addSelectionListener(new SelectionAdapter()
        {
            @Override
            public void widgetSelected(SelectionEvent event)
            {
                MessageDialog.openInformation(shell, "关于本工具", "代码备份恢复工具。\n\n00fly 于2010年5月。");
            }
        });
        shell.setMenuBar(m);
    }
    
    public void setContent()
    {
        TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
        tabFolder.setBounds(5, 2, 525, 328);
        TabItem item = new TabItem(tabFolder, SWT.NONE);
        item.setText(" 代码备份 ");
        item.setControl(new BakPanlTab(tabFolder, SWT.NONE));
        TabItem item2 = new TabItem(tabFolder, SWT.NONE);
        item2.setText(" 代码恢复 ");
        item2.setControl(new RestorePanlTab(tabFolder, SWT.NONE));
    }
    
    // 备份面板
    class BakPanlTab extends Composite
    {
        Button pwdButton;
        
        Text tpwd = new Text(this, SWT.NONE);
        
        public BakPanlTab(Composite c, int style)
        {
            super(c, style);
            Label sourceLabel = new Label(this, SWT.NONE);
            sourceLabel.setText("项目源文件目录:");
            sourceLabel.setBounds(20, 10, 100, 18);
            final Text tsourcePath = new Text(this, SWT.BORDER);
            tsourcePath.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
            tsourcePath.setEditable(false);
            tsourcePath.setBounds(120, 10, 300, 20);
            Button sourceBrowse = new Button(this, SWT.PUSH);
            sourceBrowse.setText("选择");
            sourceBrowse.setBounds(430, 10, 70, 20);
            sourceBrowse.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    DirectoryDialog dialog = new DirectoryDialog(shell);
                    dialog.setFilterPath(tsourcePath.getText());
                    String fileName = dialog.open();
                    if (fileName != null)
                    {
                        if (fileName.endsWith("\\"))
                        {
                            tsourcePath.setText(fileName);
                        }
                        else
                        {
                            tsourcePath.setText(fileName + "\\");
                        }
                        // 新源文件目录被选中，清空密码
                        tpwd.setText("");
                        pwdButton.setEnabled(true);
                    }
                }
            });
            Label fileTypeLabel = new Label(this, SWT.NONE);
            fileTypeLabel.setText("源文件类型:");
            fileTypeLabel.setBounds(20, 40, 100, 18);
            
            listJava = new org.eclipse.swt.widgets.List(this, SWT.BORDER | SWT.V_SCROLL | SWT.SIMPLE | SWT.MULTI);
            listJava.setBounds(120, 40, 120, 128);
            listJava.setToolTipText("选择需要备份的源文件类型,支持多选!");
            String[] fileTypes = {".java", ".xml", ".yml", ".yaml", ".properties", ".sql", "Dockerfile"};
            listJava.setItems(fileTypes);
            IntStream.range(0, fileTypes.length).forEach(index -> listJava.select(index));
            
            listPage = new org.eclipse.swt.widgets.List(this, SWT.BORDER | SWT.V_SCROLL | SWT.SIMPLE | SWT.MULTI);
            listPage.setBounds(280, 40, 120, 128);
            listPage.setToolTipText("选择需要备份的源文件类型,支持多选!");
            String[] fileTypes2 = {".htm", ".html", ".json", ".js", ".css", ".vue", ".jsp", ".sh"};
            listPage.setItems(fileTypes2);
            IntStream.range(0, fileTypes2.length).forEach(index -> listPage.select(index));
            
            Label pwdLabel = new Label(this, SWT.NONE);
            pwdLabel.setText("可选项:");
            pwdLabel.setBounds(20, 180, 100, 18);
            pwdButton = new Button(this, SWT.PUSH);
            pwdButton.setText("设置密码");
            pwdButton.setBounds(120, 180, 100, 20);
            pwdButton.setEnabled(false);
            pwdButton.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    InputDialog dlg = new InputDialog(shell, "带密码备份", "请输入8位密码（包括字母，数字和字符）：", "", new LengthValidator());
                    if (dlg.open() == Window.OK)
                    {
                        tpwd.setText(dlg.getValue());
                        MessageDialog.openInformation(shell, "恭喜你", "密码设置成功！");
                    }
                }
            });
            Label bakeLabel = new Label(this, SWT.NONE);
            bakeLabel.setText("备份至目录:");
            bakeLabel.setBounds(20, 210, 100, 18);
            final Text tbakPath = new Text(this, SWT.BORDER);
            tbakPath.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
            tbakPath.setEditable(false);
            tbakPath.setText(new File(" ").getAbsolutePath().trim());
            tbakPath.setBounds(120, 210, 300, 20);
            Button bakBrowse = new Button(this, SWT.PUSH);
            bakBrowse.setText("选择");
            bakBrowse.setBounds(430, 210, 70, 20);
            bakBrowse.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    DirectoryDialog dialog = new DirectoryDialog(shell);
                    dialog.setFilterPath(tbakPath.getText());
                    String fileName = dialog.open();
                    if (fileName != null)
                    {
                        if (fileName.endsWith("\\"))
                        {
                            tbakPath.setText(fileName);
                        }
                        else
                        {
                            tbakPath.setText(fileName + "\\");
                        }
                    }
                }
            });
            Button bakButton = new Button(this, SWT.PUSH);
            bakButton.setText("开始备份");
            bakButton.setBounds(220, 250, 100, 40);
            bakButton.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    if ("".equals(tsourcePath.getText()))
                    {
                        MessageDialog.openWarning(shell, "警告", "项目源文件目录不可为空!");
                        return;
                    }
                    if (listJava.getSelectionCount() + listPage.getSelectionCount() < 1)
                    {
                        MessageDialog.openError(shell, "警告", "请选择源文件类型,支持多选!");
                        listJava.setFocus();
                        return;
                    }
                    String sourcePath = tsourcePath.getText();
                    String bakFileName = tbakPath.getText() + new File(sourcePath).getName() + DateUtil.getCurrDateTimeStr() + ".bak";
                    try
                    {
                        List<String> fileTypes = new ArrayList<String>();
                        for (String it : listJava.getSelection())
                        {
                            fileTypes.add(it);
                        }
                        for (String it : listPage.getSelection())
                        {
                            fileTypes.add(it);
                        }
                        String pwdtext = tpwd.getText();
                        IRunnableWithProgress runnable = new RunProgress(sourcePath, bakFileName, fileTypes, pwdtext);
                        new ProgressMonitorDialog(shell).run(true, false, runnable);
                        String message = "创建明文备份文件 " + bakFileName + " 成功！";
                        if (!"".equals(pwdtext))
                        {
                            message = "创建加密备份文件 " + bakFileName + " 成功！";
                        }
                        MessageDialog.openInformation(shell, "提示", message);
                    }
                    catch (InvocationTargetException e)
                    {
                        MessageDialog.openError(shell, "警告", e.getMessage());
                    }
                    catch (InterruptedException e)
                    {
                        MessageDialog.openInformation(shell, "Cancelled", "刷新操作被用户取消！");
                    }
                    catch (RuntimeException e)
                    {
                        MessageDialog.openError(shell, "错误", "创建备份文件 " + bakFileName + " 失败！");
                    }
                    if (MessageDialog.openConfirm(shell, "查看备份文件", "处理完成，是否直接查看文件?"))
                    {
                        try
                        {
                            Desktop.getDesktop().open(new File(bakFileName).getParentFile());
                        }
                        catch (IOException e)
                        {
                        }
                    }
                }
            });
        }
        
        // 密码长度验证
        class LengthValidator implements IInputValidator
        {
            @Override
            public String isValid(String newText)
            {
                int len = newText.length();
                if (len < 8)
                {
                    return "长度少于8位";
                }
                if (len > 8)
                {
                    return "长度大于8位";
                }
                return null;
            }
        }
    }
    
    // 恢复面板
    class RestorePanlTab extends Composite
    {
        public RestorePanlTab(Composite c, int style)
        {
            super(c, style);
            Label bakeLabel = new Label(this, SWT.NONE);
            bakeLabel.setText("选择备份文件:");
            bakeLabel.setBounds(20, 30, 100, 18);
            final Text tbakPath = new Text(this, SWT.BORDER);
            tbakPath.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
            tbakPath.setEditable(false);
            tbakPath.setBounds(120, 30, 300, 20);
            Button bakBrowse = new Button(this, SWT.PUSH);
            bakBrowse.setText("选择");
            bakBrowse.setBounds(430, 30, 70, 20);
            bakBrowse.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
                    fileDialog.setText("选择文件");
                    String[] filterExt = {"*.bak"};
                    fileDialog.setFilterExtensions(filterExt);
                    String selected = fileDialog.open();
                    if (selected == null)
                    {
                        return;
                    }
                    tbakPath.setText(selected);
                }
            });
            Label sourceLabel = new Label(this, SWT.NONE);
            sourceLabel.setText("恢复至目录:");
            sourceLabel.setBounds(20, 100, 100, 18);
            final Text tsourcePath = new Text(this, SWT.BORDER);
            tsourcePath.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
            tsourcePath.setEditable(false);
            tsourcePath.setText(new File(" ").getAbsolutePath().trim());
            tsourcePath.setBounds(120, 100, 300, 20);
            Button sourceBrowse = new Button(this, SWT.PUSH);
            sourceBrowse.setText("选择");
            sourceBrowse.setBounds(430, 100, 70, 20);
            sourceBrowse.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    DirectoryDialog dialog = new DirectoryDialog(shell);
                    dialog.setFilterPath(tsourcePath.getText());
                    String fileName = dialog.open();
                    if (fileName != null)
                    {
                        if (fileName.endsWith("\\"))
                        {
                            tsourcePath.setText(fileName);
                        }
                        else
                        {
                            tsourcePath.setText(fileName + "\\");
                        }
                    }
                }
            });
            Button resetButton = new Button(this, SWT.PUSH);
            resetButton.setText("开始恢复");
            resetButton.setBounds(220, 170, 100, 40);
            resetButton.addSelectionListener(new SelectionAdapter()
            {
                @Override
                public void widgetSelected(SelectionEvent event)
                {
                    if ("".equals(tbakPath.getText()) || "".equals(tsourcePath.getText()))
                    {
                        MessageDialog.openWarning(shell, "警告", "备份文件或恢复目录不可为空!");
                    }
                    else
                    {
                        String dir = tsourcePath.getText();
                        try
                        {
                            new Service().createSourceFile(tbakPath.getText(), dir);
                            MessageDialog.openInformation(shell, "提示", "恢复文件到目录: " + dir + " 成功！");
                        }
                        catch (RuntimeException e)
                        {
                            MessageDialog.openError(shell, "错误", "恢复文件失败，请重新检查备份文件！");
                        }
                    }
                }
            });
        }
    }
}